/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Engine2D.graphics;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL11;

/**
 *
 * @author Garys
 */
public class GLTexture {

    private int texture[];
    private int width;
    private int height;
    private boolean tile;

    /**
     * 
     * @param mFilename
     * @param mTile
     */
    public GLTexture(String mFilename, boolean mTile) {
        texture = new int[1];
        tile = mTile;
        loadGLTexture(mFilename);
    }
    
    /**
     * 
     * @param mPath
     */
    public void loadGLTexture(String mPath) {
        
        if (mPath.endsWith(".png") || mPath.endsWith(".bmp")
                || mPath.endsWith(".jpg"))
            texture[0] = getTexture(mPath);
        else {
            System.out.println("Image not supported (only PNGs, JPGs and BMPs)");
            System.exit(1);
        }
    }

    /**
     * 
     */
    public void bind() {
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture[0]);
    }

    private int getTexture(String mPath) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(new File(mPath));
        } catch (FileNotFoundException e) {
            // System.out.println("File not found: " + mPath);
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // Exctract The Image
        BufferedImage bImage =
                new BufferedImage(image.getWidth(), image.getWidth(),
                        BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g = (Graphics2D) bImage.getGraphics();
        g.drawImage(image, null, null);
        g.dispose();
        
        // Flip Image
        AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -image.getHeight(null));
        AffineTransformOp op =
                new AffineTransformOp(tx,
                        AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        bImage = op.filter(bImage, null);

        Raster r = bImage.getRaster();
        // pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels);
        width = r.getWidth();
        height = r.getHeight();

        // Put Image In Memory
        ByteBuffer scratch =
                ByteBuffer.allocateDirect(4 * bImage.getWidth()
                        * bImage.getHeight());

        byte[] data =
                (byte[]) bImage.getRaster().getDataElements(0, 0,
                        bImage.getWidth(), bImage.getHeight(), null);
        scratch.clear();
        scratch.put(data);
        scratch.rewind();

        // Create A IntBuffer For Image Address In Memory
        IntBuffer buf =
                ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder())
                        .asIntBuffer();
        GL11.glGenTextures(buf); // Create Texture In OpenGL

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
        // Typical Texture Generation Using Data From The Image

        if (tile) {
            GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S,
                    GL11.GL_REPEAT);
            GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T,
                    GL11.GL_REPEAT);
        }

        // Linear Filtering
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
                GL11.GL_LINEAR);
        // Linear Filtering
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
                GL11.GL_LINEAR);
        // Generate The Texture
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, bImage
                .getWidth(), bImage.getHeight(), 0, GL11.GL_RGBA,
                GL11.GL_UNSIGNED_BYTE, scratch);

        return buf.get(0); // Return Image Address In Memory
        
    }

    /**
     * 
     * @return
     */
    public int getWidth() {
        return width;
    }

   /**
    * 
    * @return
    */
   public int getHeight() {
        return height;
    }
}
